package com.example.ssrbac.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * JWT认证过滤器
 * 
 * 该过滤器负责处理每个请求的JWT token验证和用户认证
 * 主要功能包括：
 * 1. 从请求头中提取JWT token
 * 2. 验证token的有效性
 * 3. 检查token是否在黑名单中
 * 4. 加载用户信息
 * 5. 设置认证信息到SecurityContext
 * 
 * @author Your Name
 * @version 1.0
 */
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
    // 使用SLF4J进行日志记录
    private static final Logger logger = LoggerFactory.getLogger(JwtRequestFilter.class);

    /**
     * 用户详情服务，用于加载用户信息
     */
    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * JWT工具类，用于处理token
     */
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 处理每个请求的过滤器方法
     * 
     * @param request HTTP请求
     * @param response HTTP响应
     * @param chain 过滤器链
     * @throws ServletException 如果发生Servlet异常
     * @throws IOException 如果发生IO异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        
        // 从请求头中获取token
        final String requestTokenHeader = request.getHeader("Authorization");
        logger.debug("处理请求: {}，Token: {}", request.getRequestURI(), requestTokenHeader);

        String username = null;
        String jwtToken = null;

        // 从请求头中获取token
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
            jwtToken = requestTokenHeader.substring(7);
            
            try {
                // 检查token是否在黑名单中
                Boolean isBlacklisted = redisTemplate.hasKey("blacklist:" + jwtToken);
                if (Boolean.TRUE.equals(isBlacklisted)) {
                    logger.warn("Token在黑名单中: {}", jwtToken);
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token已失效");
                    return;
                }

                // 从token中获取用户名
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
                logger.debug("从token中获取用户名: {}", username);
            } catch (Exception e) {
                logger.error("处理token时发生错误", e);
            }
        }

        // 验证token
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
                // 创建认证信息
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                
                // 设置认证信息到SecurityContext
                SecurityContextHolder.getContext().setAuthentication(authentication);
                logger.debug("用户 {} 认证成功", username);
            } else {
                logger.warn("token验证失败: {}", jwtToken);
            }
        }

        // 继续处理请求
        chain.doFilter(request, response);
    }
} 